<?php
if(!interface_exists('XRouteParser', false)){
	require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'XRouteParser.php');
}
final class XRESTRouteParser extends XObject implements XRouteParser{
	public function parse($dir, $route, $params = array()){		
		$rules = XConfig::singleton()->get('project.route.rules');
		if(is_array($rules) && count($rules) > 0){
			foreach($rules as $rule){
				if($this->_applyRule($rule, $dir, $route, $params)){
					return true;
				}
			}
		}
		$newRoute = urldecode(preg_replace("/\/(\d+)[\?\/]*/i", '', $route));
		$newParams = $params;
		preg_match("/\/(\d+)[\?\/]*/i", $route, $id);
		if(isset($id[1])){
			$newParams['id'] = $id[1];
		}
		$names = preg_split('/\/+/i', $newRoute, 0, PREG_SPLIT_NO_EMPTY);
		$count = count($names);
		//first match: $route = controller + action		
		if($count >= 2){
			$path = implode('/', array_slice($names, 0, $count-2));
			if($this->_controller('/'.$path.'/'.$names[$count-2], $dir.'/'.$path, $names[$count-2], $names[$count-1], $newParams)){
				return true;
			}
		}
		//second match: $route = controller, action = index
		if($count >= 1){
			$path = implode('/', array_slice($names, 0, $count-1));
			if($this->_controller('/'.$path.'/'.$names[$count-1], $dir.'/'.$path, $names[$count-1], 'index', $newParams)){
				return true;
			}
		}
		//third match: $route/index.php = controller, action = index
		if($this->_controller('/'.$newRoute.'/index', $dir.'/'.$newRoute, 'index', 'index', $newParams)){
			return true;
		}
		return false;
	}
	
	private function _applyRule($rule, $dir, $route, $params = array()){		
		if(!isset($rule['pattern']) || !isset($rule['controller'])){
			return false;
		}
		if(!preg_match("/{$rule['pattern']}/i", $route)){
			return false;
		}
		$controllerName = x_preg_split_tail('/\/+/i', $rule['controller']);		
		$path = $dir.'/'.$rule['controller'];
		$path = preg_replace("/\/*{$controllerName}$/i", '', $path);
		$actionName = isset($rule['action']) ? $rule['action'] : 'doIndex';
		if(!isset($rule['params_prefix'])
			|| !isset($rule['params']) 
			|| count($rule['params']) == 0){
			return $this->_controller('/'.$rule['controller'], $path, $controllerName, $actionName, $params);
		}
		$newParams = $params;
		preg_match("/{$rule['params_prefix']}(.+)/i", $route, $match);
		if(isset($match[1])){
			$array = preg_split('/\/+/i', $match[1], 0, PREG_SPLIT_NO_EMPTY);
			foreach($rule['params'] as $value){
				$newParams[$value] = array_shift($array);
			}
		}
		return $this->_controller('/'.$rule['controller'], $path, $controllerName, $actionName, $newParams);
	}
	
	private function _controller($route, $path, $controllerName, $actionName, $params = array()){
		$className = x_class_name($controllerName).'Controller';
		$newActionName = 'do'.x_name_to_java($actionName);
		return XRouter::singleton()->loadController($route, $path.'/'.$className.'.php', $className, $newActionName, $params);
	}
}
?>